from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, ConfigDict, validator
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta
import json
import threading

from config import config
from utils import LogManager, metrics_collector
from sample_manager import sample_manager
from inference_engine import inference_engine
from cloud_client import cloud_client

# 数据模型
class SampleInfoResponse(BaseModel):
    """样本信息响应模型"""
    node_id: str
    task_name: str
    collected_sample_count: int
    uncollected_sample_count: int
    uninferred_sample_count: int
    total_sample_count: int
    difficulty_threshold_stats: Dict[str, int]
    timestamp: str

class DataAggregationRequest(BaseModel):
    """数据聚合请求模型"""
    difficulty_threshold: Optional[float] = Field(None, ge=0.0, le=1.0)
    time_start: Optional[str] = None
    time_end: Optional[str] = None
    max_samples: Optional[int] = Field(None, gt=0, le=10000)
    
    @validator('time_start', 'time_end')
    def validate_time_format(cls, v):
        if v is not None:
            try:
                datetime.fromisoformat(v.replace('Z', '+00:00'))
            except ValueError:
                raise ValueError('时间格式必须为ISO格式')
        return v

class DataAggregationResponse(BaseModel):
    """数据聚合响应模型"""
    success: bool
    message: str
    selected_samples: List[str]
    sample_count: int
    upload_info: Optional[Dict] = None

class ModelUpdateRequest(BaseModel):
    """模型更新请求模型"""
    model_config = ConfigDict(protected_namespaces=())
    
    model_id: str
    model_url: str
    model_path: Optional[str] = None

class EdgeServer:
    """边侧服务器"""
    
    def __init__(self):
        self.logger = LogManager.get_logger("EdgeServer")
        self.upload_tasks = {}  # 存储上传任务状态
        self.tasks_lock = threading.Lock()  # 线程锁保护任务字典
        self.app = self.create_app()
    
    def create_app(self) -> FastAPI:
        """创建FastAPI应用"""
        app = FastAPI(
            title="边侧节点API",
            description="边侧节点数据管理和推理服务",
            version="1.0.0",
        )
        
        # 添加CORS中间件
        app.add_middleware(
            CORSMiddleware,
            allow_origins=["*"],
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"],
        )
        
        # 健康检查
        @app.get("/health")
        async def health_check():
            """基础健康检查"""
            return {
                "status": "healthy",
                "node_id": config.edge_node.id,
                "timestamp": datetime.now().isoformat(),
                "model_loaded": inference_engine.has_model(),
                "service": "边缘节点服务"
            }
        
        # 详细健康检查
        @app.get("/health/detailed")
        async def detailed_health_check():
            """详细健康检查"""
            try:
                from edge_main import edge_main
                import psutil
                
                health_info = {
                    "status": "healthy",
                    "node_id": config.edge_node.id,
                    "timestamp": datetime.now().isoformat(),
                    "service": "边缘节点服务",
                    "components": {}
                }
                
                # 检查推理引擎状态
                try:
                    model_loaded = inference_engine.has_model()
                    health_info["components"]["inference"] = {
                        "status": "healthy" if model_loaded else "warning",
                        "model_loaded": model_loaded,
                        "model_path": inference_engine.model_path if model_loaded else None,
                        "message": "推理引擎正常" if model_loaded else "未加载模型"
                    }
                    
                    if not model_loaded and health_info["status"] == "healthy":
                        health_info["status"] = "warning"
                        
                except Exception as e:
                    health_info["components"]["inference"] = {
                        "status": "error",
                        "error": str(e)
                    }
                    health_info["status"] = "degraded"
                
                # 检查云端连接状态
                try:
                    cloud_connected = cloud_client.check_cloud_connection()
                    health_info["components"]["cloud_connection"] = {
                        "status": "healthy" if cloud_connected else "warning",
                        "connected": cloud_connected,
                        "cloud_url": config.cloud_server.base_url,
                        "message": "云端连接正常" if cloud_connected else "无法连接到云端"
                    }
                    
                    if not cloud_connected and health_info["status"] == "healthy":
                        health_info["status"] = "warning"
                        
                except Exception as e:
                    health_info["components"]["cloud_connection"] = {
                        "status": "error",
                        "error": str(e)
                    }
                    health_info["status"] = "degraded"
                
                # 检查样本管理状态
                try:
                    sample_stats = sample_manager.get_sample_statistics()
                    health_info["components"]["samples"] = {
                        "status": "healthy",
                        "statistics": sample_stats,
                        "message": f"样本管理正常，总计 {sample_stats.get('total_inferred_samples', 0)} 个已推理样本"
                    }
                except Exception as e:
                    health_info["components"]["samples"] = {
                        "status": "warning",
                        "error": str(e)
                    }
                    if health_info["status"] == "healthy":
                        health_info["status"] = "warning"
                
                # 检查系统资源
                try:
                    cpu_percent = psutil.cpu_percent(interval=1)
                    memory = psutil.virtual_memory()
                    disk = psutil.disk_usage('/')
                    
                    health_info["components"]["system"] = {
                        "status": "healthy",
                        "cpu_usage": f"{cpu_percent:.1f}%",
                        "memory_usage": f"{memory.percent:.1f}%",
                        "disk_usage": f"{disk.percent:.1f}%",
                        "memory_available": f"{memory.available / 1024**3:.1f}GB",
                        "disk_free": f"{disk.free / 1024**3:.1f}GB"
                    }
                    
                    # 资源使用率过高时发出警告
                    if cpu_percent > 90 or memory.percent > 90 or disk.percent > 90:
                        health_info["components"]["system"]["status"] = "warning"
                        if health_info["status"] == "healthy":
                            health_info["status"] = "warning"
                            
                except Exception as e:
                    health_info["components"]["system"] = {
                        "status": "unknown",
                        "error": str(e)
                    }
                
                # 检查上传任务状态
                try:
                    with self.tasks_lock:
                        active_tasks = len([t for t in self.upload_tasks.values() if t["status"] in ["processing", "uploading"]])
                        failed_tasks = len([t for t in self.upload_tasks.values() if t["status"] == "failed"])
                        completed_tasks = len([t for t in self.upload_tasks.values() if t["status"] == "completed"])
                    
                    health_info["components"]["upload_tasks"] = {
                        "status": "healthy",
                        "active_tasks": active_tasks,
                        "failed_tasks": failed_tasks,
                        "completed_tasks": completed_tasks,
                        "total_tasks": len(self.upload_tasks)
                    }
                    
                    if failed_tasks > 0 and health_info["status"] == "healthy":
                        health_info["status"] = "warning"
                        health_info["components"]["upload_tasks"]["status"] = "warning"
                        
                except Exception as e:
                    health_info["components"]["upload_tasks"] = {
                        "status": "unknown",
                        "error": str(e)
                    }
                
                # 检查关键目录
                try:
                    from pathlib import Path
                    
                    dirs_to_check = {
                        "temp_dir": Path(config.dataset.temp_dir),
                        "dataset_dir": Path(config.dataset.datasets_dir),
                        "models_dir": Path("models"),
                        "logs_dir": Path("logs")
                    }
                    
                    dir_status = {}
                    for name, path in dirs_to_check.items():
                        dir_status[name] = {
                            "exists": path.exists(),
                            "is_dir": path.is_dir() if path.exists() else False,
                            "file_count": len(list(path.iterdir())) if path.exists() and path.is_dir() else 0
                        }
                    
                    health_info["components"]["directories"] = {
                        "status": "healthy",
                        "details": dir_status
                    }
                    
                    # 检查是否有目录不存在
                    missing_dirs = [name for name, info in dir_status.items() if not info["exists"]]
                    
                    if missing_dirs:
                        health_info["components"]["directories"]["status"] = "warning"
                        health_info["components"]["directories"]["missing"] = missing_dirs
                        if health_info["status"] == "healthy":
                            health_info["status"] = "warning"
                            
                except Exception as e:
                    health_info["components"]["directories"] = {
                        "status": "unknown",
                        "error": str(e)
                    }
                
                return health_info
                
            except Exception as e:
                self.logger.error(f"详细健康检查失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"健康检查失败: {str(e)}")
        
        # Ping接口
        @app.get("/health/ping")
        async def ping():
            """简单的ping接口"""
            return {
                "ping": "pong", 
                "node_id": config.edge_node.id,
                "timestamp": datetime.now().isoformat()
            }
        
        # 获取样本信息
        @app.get("/samples/info", response_model=SampleInfoResponse)
        async def get_sample_info():
            """获取样本信息"""
            try:
                sample_stats = sample_manager.get_sample_statistics()
                
                if not sample_stats:
                    raise HTTPException(status_code=500, detail="获取样本统计信息失败")
                
                return SampleInfoResponse(
                    node_id=config.edge_node.id,
                    task_name=sample_stats.get("task_name", "设备缺陷识别"),
                    collected_sample_count=sample_stats.get("collected_samples", 0),
                    uncollected_sample_count=sample_stats.get("uncollected_samples", 0),
                    uninferred_sample_count=sample_stats.get("uninferred_samples", 0),
                    total_sample_count=sample_stats.get("total_inferred_samples", 0) + sample_stats.get("uninferred_samples", 0),
                    difficulty_threshold_stats=sample_stats.get("difficulty_distribution", {}),
                    timestamp=sample_stats.get("timestamp", datetime.now().isoformat())
                )
                
            except Exception as e:
                self.logger.error(f"获取样本信息失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"获取样本信息失败: {str(e)}")
        
        # 数据聚合接口
        @app.post("/samples/aggregate", response_model=DataAggregationResponse)
        async def aggregate_samples(
            request: DataAggregationRequest,
            background_tasks: BackgroundTasks
        ):
            """数据聚合请求"""
            try:
                # 验证时间范围
                time_range = None
                if request.time_start and request.time_end:
                    try:
                        start_time = datetime.fromisoformat(request.time_start.replace('Z', '+00:00'))
                        end_time = datetime.fromisoformat(request.time_end.replace('Z', '+00:00'))
                        
                        if start_time >= end_time:
                            raise ValueError("开始时间必须早于结束时间")
                        
                        time_range = (start_time, end_time)
                    except Exception as e:
                        raise HTTPException(status_code=400, detail=f"时间范围参数错误: {str(e)}")
                
                # 选择样本
                selected_samples = sample_manager.select_samples_for_aggregation(
                    difficulty_threshold=request.difficulty_threshold,
                    time_range=time_range,
                    max_samples=request.max_samples
                )
                
                if not selected_samples:
                    return DataAggregationResponse(
                        success=True,
                        message="没有符合条件的样本",
                        selected_samples=[],
                        sample_count=0
                    )
                
                # 生成任务ID
                task_id = f"upload_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{len(selected_samples)}"
                
                # 记录任务状态（线程安全）
                with self.tasks_lock:
                    self.upload_tasks[task_id] = {
                        "status": "processing",
                        "samples": selected_samples,
                        "started_at": datetime.now().isoformat(),
                        "message": "正在上传样本数据"
                    }
                
                # 在后台任务中上传样本
                background_tasks.add_task(
                    self._upload_samples_background, 
                    task_id,
                    selected_samples,
                    request.dict()
                )
                
                return DataAggregationResponse(
                    success=True,
                    message=f"已选择 {len(selected_samples)} 个样本进行聚合",
                    selected_samples=selected_samples,
                    sample_count=len(selected_samples),
                    upload_info={"task_id": task_id, "status": "processing"}
                )
                
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"数据聚合失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"数据聚合失败: {str(e)}")
        
        # 上传状态查询接口
        @app.get("/samples/upload/{task_id}")
        async def get_upload_status(task_id: str):
            """查询上传任务状态"""
            with self.tasks_lock:
                if task_id not in self.upload_tasks:
                    raise HTTPException(status_code=404, detail="任务不存在")
                
                task_info = self.upload_tasks[task_id].copy()  # 创建副本避免锁外访问
            
            return {
                "task_id": task_id,
                "status": task_info["status"],
                "message": task_info["message"],
                "sample_count": len(task_info["samples"]),
                "started_at": task_info["started_at"],
                "completed_at": task_info.get("completed_at")
            }
        
        # 获取所有上传任务状态
        @app.get("/samples/upload")
        async def get_all_upload_status():
            """获取所有上传任务状态"""
            tasks = []
            with self.tasks_lock:
                for task_id, task_info in self.upload_tasks.items():
                    tasks.append({
                        "task_id": task_id,
                        "status": task_info["status"],
                        "sample_count": len(task_info["samples"]),
                        "started_at": task_info["started_at"],
                        "completed_at": task_info.get("completed_at")
                    })
            return {"tasks": tasks}
        
        # 系统状态接口
        @app.get("/status")
        async def get_system_status():
            """获取系统详细状态"""
            try:
                from edge_main import edge_main
                
                # 获取样本统计
                sample_stats = sample_manager.get_sample_statistics()
                
                # 获取系统指标
                system_metrics = metrics_collector.get_system_metrics()
                
                # 获取模型信息
                model_info = None
                if inference_engine.has_model():
                    model_info = {
                        "loaded": True,
                        "model_path": inference_engine.model_path,
                        "metadata": inference_engine.model_metadata
                    }
                else:
                    model_info = {"loaded": False}
                
                return {
                    "node_id": config.edge_node.id,
                    "status": "healthy" if hasattr(edge_main, 'inference_healthy') and edge_main.inference_healthy else "degraded",
                    "uptime": system_metrics.get("uptime", 0),
                    "system_metrics": system_metrics,
                    "sample_statistics": sample_stats,
                    "model_info": model_info,
                    "service_health": {
                        "api_server": True,
                        "inference_engine": inference_engine.has_model(),
                        "node_registered": hasattr(edge_main, 'node_registered') and edge_main.node_registered,
                        "cloud_connected": cloud_client.check_cloud_connection()
                    },
                    "directories_status": self._check_directories_status(),
                    "timestamp": datetime.now().isoformat()
                }
                
            except Exception as e:
                self.logger.error(f"获取系统状态失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"获取系统状态失败: {str(e)}")
        
        def _check_directories_status():
            """检查关键目录状态"""
            from pathlib import Path
            
            dirs_to_check = {
                "temp_dir": Path(config.dataset.temp_dir),
                "dataset_dir": Path(config.dataset.datasets_dir),
                "images_dir": Path(config.dataset.datasets_dir) / 'images',
                "labels_dir": Path(config.dataset.datasets_dir) / 'labels',
                "confidence_dir": Path(config.dataset.datasets_dir) / config.dataset.confidence_dir,
                "models_dir": Path("models")
            }
            
            status = {}
            for name, path in dirs_to_check.items():
                status[name] = {
                    "exists": path.exists(),
                    "is_dir": path.is_dir() if path.exists() else False,
                    "file_count": len(list(path.iterdir())) if path.exists() and path.is_dir() else 0
                }
            
            return status
        
        # 模型更新接口
        @app.post("/model/update")
        async def update_model(request: ModelUpdateRequest):
            """更新模型"""
            try:
                success = inference_engine.update_model(
                    request.model_id, 
                    request.model_url, 
                    request.model_path
                )
                
                if success:
                    return {
                        "success": True,
                        "message": f"模型 {request.model_id} 更新成功",
                        "model_info": {
                            "model_id": request.model_id,
                            "updated_at": datetime.now().isoformat(),
                            "metadata": inference_engine.model_metadata
                        }
                    }
                else:
                    raise HTTPException(status_code=500, detail="模型更新失败")
                    
            except Exception as e:
                self.logger.error(f"模型更新失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"模型更新失败: {str(e)}")
        
        # 模型信息查询接口
        @app.get("/model/info")
        async def get_model_info():
            """获取当前模型信息"""
            try:
                if inference_engine.has_model():
                    return {
                        "loaded": True,
                        "model_path": inference_engine.model_path,
                        "metadata": inference_engine.model_metadata,
                        "timestamp": datetime.now().isoformat()
                    }
                else:
                    return {
                        "loaded": False,
                        "message": "没有加载模型",
                        "timestamp": datetime.now().isoformat()
                    }
            except Exception as e:
                self.logger.error(f"获取模型信息失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"获取模型信息失败: {str(e)}")
        
        # 手动触发推理
        @app.post("/inference/trigger")
        async def trigger_inference():
            """手动触发推理"""
            try:
                if not inference_engine.has_model():
                    raise HTTPException(status_code=400, detail="模型未加载")
                
                processed_count = inference_engine.process_temp_images()
                
                return {
                    "success": True,
                    "message": f"推理完成，处理了 {processed_count} 张图片",
                    "processed_count": processed_count
                }
                
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"手动推理失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"手动推理失败: {str(e)}")
        
        # 从云端下载模型接口
        @app.post("/model/download")
        async def download_model_from_cloud():
            """从云端下载模型"""
            try:
                self.logger.info("手动触发从云端下载模型...")
                
                # 从云端获取并下载默认模型
                success, result = cloud_client.get_default_model_from_cloud()
                
                if success:
                    self.logger.info(f"从云端下载模型成功: {result}")
                    
                    # 尝试加载下载的模型
                    if inference_engine.load_model(result):
                        return {
                            "success": True,
                            "message": f"从云端下载并加载模型成功",
                            "model_path": result,
                            "model_info": inference_engine.model_metadata
                        }
                    else:
                        raise HTTPException(status_code=500, detail="模型下载成功但加载失败")
                else:
                    raise HTTPException(status_code=500, detail=f"从云端下载模型失败: {result}")
                    
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"从云端下载模型失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"从云端下载模型失败: {str(e)}")
        
        # 获取云端可用模型列表
        @app.get("/model/available")
        async def get_available_models():
            """获取云端可用模型列表"""
            try:
                models = cloud_client.get_available_models()
                
                if models is not None:
                    if len(models) == 0:
                        return {
                            "success": True,
                            "models": [],
                            "count": 0,
                            "message": "云端当前没有可用模型",
                            "suggestions": [
                                "在云端创建训练任务生成新模型",
                                "手动上传预训练模型到云端",
                                "检查云端数据库中的模型记录"
                            ]
                        }
                    else:
                        return {
                            "success": True,
                            "models": models,
                            "count": len(models)
                        }
                else:
                    raise HTTPException(status_code=500, detail="无法连接到云端服务器获取模型列表")
                    
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"获取云端模型列表失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"获取云端模型列表失败: {str(e)}")
        
        # 检查云端连接和模型状态
        @app.get("/model/cloud-status")
        async def check_cloud_model_status():
            """检查云端连接和模型状态"""
            try:
                # 检查云端连接
                cloud_connected = cloud_client.check_cloud_connection()
                
                status_info = {
                    "cloud_connected": cloud_connected,
                    "timestamp": datetime.now().isoformat()
                }
                
                if cloud_connected:
                    # 获取模型列表
                    models = cloud_client.get_available_models()
                    if models is not None:
                        status_info.update({
                            "models_available": len(models) > 0,
                            "model_count": len(models),
                            "models": models[:3] if models else []  # 只返回前3个模型信息
                        })
                        
                        if len(models) == 0:
                            status_info["message"] = "云端连接正常，但没有可用模型"
                            status_info["recommendations"] = [
                                "创建训练任务生成模型",
                                "上传预训练模型",
                                "检查模型文件路径"
                            ]
                        else:
                            status_info["message"] = f"云端连接正常，找到 {len(models)} 个可用模型"
                    else:
                        status_info.update({
                            "models_available": False,
                            "message": "云端连接正常，但无法获取模型列表",
                            "error": "可能是API端点问题"
                        })
                else:
                    status_info.update({
                        "models_available": False,
                        "message": "无法连接到云端服务器",
                        "recommendations": [
                            "检查云端服务器是否运行",
                            "验证网络连接",
                            "确认配置文件中的云端地址"
                        ]
                    })
                
                return status_info
                
            except Exception as e:
                self.logger.error(f"检查云端模型状态失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"检查云端模型状态失败: {str(e)}")
        
        # 新增：获取sample_uploads目录中的压缩包列表
        @app.get("/samples/packages")
        async def get_sample_packages():
            """获取sample_uploads目录中的样本压缩包列表"""
            try:
                from pathlib import Path
                import os
                
                upload_dir = Path("sample_uploads")
                if not upload_dir.exists():
                    return {"packages": [], "count": 0, "message": "上传目录不存在"}
                
                packages = []
                for zip_file in upload_dir.glob("*.zip"):
                    try:
                        stat = zip_file.stat()
                        packages.append({
                            "filename": zip_file.name,
                            "size": stat.st_size,
                            "created_time": datetime.fromtimestamp(stat.st_ctime).isoformat(),
                            "modified_time": datetime.fromtimestamp(stat.st_mtime).isoformat(),
                            "size_mb": round(stat.st_size / (1024 * 1024), 2)
                        })
                    except Exception as e:
                        self.logger.warning(f"获取文件信息失败: {zip_file}, {str(e)}")
                        continue
                
                # 按创建时间降序排列
                packages.sort(key=lambda x: x["created_time"], reverse=True)
                
                return {
                    "packages": packages,
                    "count": len(packages),
                    "message": f"找到 {len(packages)} 个样本压缩包"
                }
                
            except Exception as e:
                self.logger.error(f"获取样本压缩包列表失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"获取样本压缩包列表失败: {str(e)}")
        
        # 新增：下载指定的样本压缩包
        @app.get("/samples/packages/{filename}")
        async def download_sample_package(filename: str):
            """下载指定的样本压缩包"""
            try:
                from pathlib import Path
                from fastapi.responses import FileResponse
                import os
                
                # 安全检查：只允许下载.zip文件，防止路径穿越攻击
                if not filename.endswith('.zip') or '/' in filename or '\\' in filename:
                    raise HTTPException(status_code=400, detail="无效的文件名")
                
                upload_dir = Path("sample_uploads")
                file_path = upload_dir / filename
                
                if not file_path.exists():
                    raise HTTPException(status_code=404, detail="文件不存在")
                
                if not file_path.is_file():
                    raise HTTPException(status_code=400, detail="不是有效的文件")
                
                self.logger.info(f"云端下载样本压缩包: {filename}")
                
                return FileResponse(
                    path=str(file_path),
                    filename=filename,
                    media_type='application/zip'
                )
                
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"下载样本压缩包失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"下载样本压缩包失败: {str(e)}")
        
        # 新增：删除指定的样本压缩包
        @app.delete("/samples/packages/{filename}")
        async def delete_sample_package(filename: str):
            """删除指定的样本压缩包"""
            try:
                from pathlib import Path
                
                # 安全检查
                if not filename.endswith('.zip') or '/' in filename or '\\' in filename:
                    raise HTTPException(status_code=400, detail="无效的文件名")
                
                upload_dir = Path("sample_uploads")
                file_path = upload_dir / filename
                
                if not file_path.exists():
                    raise HTTPException(status_code=404, detail="文件不存在")
                
                file_path.unlink()
                self.logger.info(f"删除样本压缩包: {filename}")
                
                return {
                    "success": True,
                    "message": f"成功删除压缩包: {filename}"
                }
                
            except HTTPException:
                raise
            except Exception as e:
                self.logger.error(f"删除样本压缩包失败: {str(e)}")
                raise HTTPException(status_code=500, detail=f"删除样本压缩包失败: {str(e)}")
        
        return app
    
    async def _upload_samples_background(self, task_id: str, sample_names: List[str], request_params: Dict):
        """后台上传样本任务"""
        try:
            self.logger.info(f"开始后台上传样本: {len(sample_names)} 个，任务ID: {task_id}")
            
            # 更新任务状态为上传中
            with self.tasks_lock:
                if task_id in self.upload_tasks:
                    self.upload_tasks[task_id]["status"] = "uploading"
                    self.upload_tasks[task_id]["message"] = "正在打包和上传样本数据"
            
            # 打包并上传样本
            success, result = sample_manager.package_and_upload_samples(sample_names)
            
            # 更新任务状态（线程安全）
            with self.tasks_lock:
                if task_id in self.upload_tasks:
                    if success:
                        self.upload_tasks[task_id].update({
                            "status": "completed",
                            "message": result.get('message', '样本上传完成'),
                            "completed_at": datetime.now().isoformat()
                        })
                        self.logger.info(f"样本上传成功: {result}")
                    else:
                        self.upload_tasks[task_id].update({
                            "status": "failed", 
                            "message": result.get('error', '上传失败'),
                            "completed_at": datetime.now().isoformat()
                        })
                        self.logger.error(f"样本上传失败: {result}")
                
        except Exception as e:
            self.logger.error(f"后台上传样本异常: {str(e)}")
            # 更新任务状态为失败（线程安全）
            with self.tasks_lock:
                if task_id in self.upload_tasks:
                    self.upload_tasks[task_id].update({
                        "status": "failed",
                        "message": f"上传异常: {str(e)}",
                        "completed_at": datetime.now().isoformat()
                    })
    
    def cleanup_old_tasks(self, max_age_hours: int = 24):
        """清理旧的上传任务记录"""
        try:
            cutoff_time = datetime.now() - timedelta(hours=max_age_hours)
            
            with self.tasks_lock:
                tasks_to_remove = []
                for task_id, task_info in self.upload_tasks.items():
                    if task_info.get("completed_at"):
                        completed_time = datetime.fromisoformat(task_info["completed_at"])
                        if completed_time < cutoff_time:
                            tasks_to_remove.append(task_id)
                
                for task_id in tasks_to_remove:
                    del self.upload_tasks[task_id]
                
                if tasks_to_remove:
                    self.logger.debug(f"清理了 {len(tasks_to_remove)} 个旧的上传任务记录")
                
        except Exception as e:
            self.logger.warning(f"清理旧任务记录失败: {str(e)}")

# 全局边侧服务器实例
edge_server = EdgeServer() 